import * as Cesium from '@cesiumjs';
import {
  G3xObjBase
} from "@g3xbase"
import {
  autorun,
  reaction,
  intercept,
  extendObservable,
  computed
} from 'mobx';
import Contour from "./Contour"
import ElevationRamp from "./ElevationRamp"
import SlopeRamp from "./SlopeRamp"
import AspectRamp from "./AspectRamp"
import Restrict from "./Restrict"

/* 477 */
/**
 * 地形特效
 * @class
 */
class G3xTerrainEffect extends G3xObjBase {
  constructor(viewer, options) {

    super(viewer, options);

    var _this = this;
    _this._viewer = viewer;
    _this._scene = viewer.scene;
    _this._globe = _this._scene.globe;

    this.init()
  }

  init() {
    var _this = this;
    _this.contour = new Contour(_this);
    _this.elevation = new ElevationRamp(_this);
    _this.slope = new SlopeRamp(_this);
    _this.aspect = new AspectRamp(_this);
    _this.restrict = new Restrict(_this);

    _this.disposers.push(function() {
      _this.contour = _this.contour && _this.contour.destroy();
      _this.elevation = _this.elevation && _this.elevation.destroy();
      _this.slope = _this.slope && _this.slope.destroy();
      _this.aspect = _this.aspect && _this.aspect.destroy();
      _this.restrict = _this.restrict && _this.restrict.destroy();
    });

    _this.disposers.push(_XbsjBase3.default.registerProperty(_this, 'restrict'));
    _this.disposers.push(_XbsjBase3.default.registerProperty(_this, 'contour'));
    _this.disposers.push(_XbsjBase3.default.registerProperty(_this, 'elevation'));
    _this.disposers.push(_XbsjBase3.default.registerProperty(_this, 'slope'));
    _this.disposers.push(_XbsjBase3.default.registerProperty(_this, 'aspect'));

    _this._defaultImage =
      '';

    //增加一个计算属性
    extendObservable(_this, {
      /**
       * 当前启用的着色对象
       * @type {Object}
       * @default undefined
       * @readonly
       * @instance
       * @memberof TerrainEffect
       */
      get shading() {
        //根据启用性返回当前的着色
        if (this.elevation.enabled) {
          return this.elevation;
        } else if (this.slope.enabled) {
          return this.slope;
        } else if (this.aspect.enabled) {
          return this.aspect;
        }
        return undefined;
      }
    }, {
      shading: computed
    });

    _this.disposers.push(reaction(function() {
      return _this.subSurfaceEnabled;
    }, function() {
      //地下模式
      if (!_this._scene.xbsjSubsurfaceManager) {
        console.warn('地下模式插件未启用！此功能无效！');
        return;
      }

      _this._scene.xbsjSubsurfaceManager.subsurfaceEnabled = _this.subSurfaceEnabled;
    }));

    _this.disposers.push(reaction(function() {
      return _this.surfaceOpacity;
    }, function() {
      //地下模式
      if (!_this._scene.xbsjSubsurfaceManager) {
        console.warn('地下模式插件未启用！此功能无效！');
        return;
      }

      if (_this.depthTest) {
        console.warn('需要首先关闭地形深度检测(depthTest)，此功能才能有效！');
      }

      if (_this.surfaceOpacity <= 0.0) {
        _this._scene.xbsjSubsurfaceManager.transparentEnabled = false;
      } else {
        _this._scene.xbsjSubsurfaceManager.transparentEnabled = true;
        _this._scene.xbsjSubsurfaceManager.opacity = _this.surfaceOpacity;
      }
    }));

    //监控所有子的变化
    _this.disposers.push(autorun(function() {
      var a = _this.elevation;
      var b = _this.slope;
      var c = _this.aspect;
      var d = _this.contour;
      _this._update(a, b, c, d);

      _this._scene.logarithmicDepthBuffer = _this.logDepth;
      _this._globe._surface.tileProvider._debug.wireframe = _this.wireFrame;

      _this._globe.depthTestAgainstTerrain = _this.depthTest;

      //这玩意竟然是个只读属性
      // this._scene.terrainExaggeration = this.exaggeration;

      //全球光照
      _this._globe.enableLighting = _this.enableLighting;
      //是否显示
      _this._globe.show = _this.show;
    }));

    var c = _this.baseColor;
    earth.czm.viewer.scene.globe.baseColor = new Cesium.Color(c[0], c[1], c[2], c[3]);
    _this.disposers.push((0, _mobx.reaction)(function() {
      return [].concat((0, _toConsumableArray3.default)(_this.baseColor));
    }, function() {
      var c = _this.baseColor;
      earth.czm.viewer.scene.globe.baseColor = new Cesium.Color(c[0], c[1], c[2], c[3]);
    }));
    return _this;
  }
}

g3xUtils.g3x_defineClassProperties(TerrainEffect, [{
  key: '_update',
  value: function _update() {
    //更新当前材质
    this._updateMaterial();

    //等高线起效
    this.contour._apply();
    //颜色着色起效
    if (this.shading) this.shading._apply();
  }
}, {
  key: '_newContourMaterial',
  value: function _newContourMaterial(shading) {

    return new Cesium.Material({
      fabric: {
        type: "Contour" + shading,
        materials: {
          contour: {
            type: "ElevationContour"
          },
          shading: {
            type: shading
          }
        },
        components: {
          diffuse: "contour.alpha == 0.0 ? shading.diffuse : contour.diffuse",
          alpha: "max(contour.alpha, shading.alpha)"
        }
      },
      translucent: false
    });
  }
}, {
  key: '_updateMaterial',
  value: function _updateMaterial() {
    var currentMat = this._globe.material;
    //创建当前材质
    //高程着色的时候
    if (this.contour.enabled) {
      if (this.shading === this.elevation) {

        if (currentMat && currentMat.type == 'ContourElevationRamp') {
          return;
        }
        currentMat = this._newContourMaterial('ElevationRamp');
      } else if (this.shading == this.slope) {
        if (currentMat && currentMat.type == 'ContourSlopeRamp') {
          return;
        }
        currentMat = this._newContourMaterial('SlopeRamp');
      } else if (this.shading == this.aspect) {
        if (currentMat && currentMat.type == 'ContourAspectRamp') {
          return;
        }
        currentMat = this._newContourMaterial('AspectRamp');
      } else {
        if (currentMat && currentMat.type == 'ElevationContour') {
          return;
        }
        currentMat = Cesium.Material.fromType("ElevationContour");
      }
    } else {
      if (this.shading === this.elevation) {
        if (currentMat && currentMat.type == 'ElevationRamp') {
          return;
        }
        currentMat = Cesium.Material.fromType("ElevationRamp");
      } else if (this.shading == this.slope) {
        if (currentMat && currentMat.type == 'SlopeRamp') {
          return;
        }
        currentMat = Cesium.Material.fromType("SlopeRamp");
      } else if (this.shading == this.aspect) {
        if (currentMat && currentMat.type == 'AspectRamp') {
          return;
        }
        currentMat = Cesium.Material.fromType("AspectRamp");
      } else {
        currentMat = undefined;
      }
    }

    //更新材质
    this._globe.material = currentMat;
  }
}, {
  key: 'destroy',
  value: function destroy() {
    return (0, _get3.default)(TerrainEffect.prototype.__proto__ || (0, _getPrototypeOf2.default)(
      TerrainEffect.prototype), 'destroy', this).call(this);
  }
}, {
  key: '_createImage',
  value: function _createImage(base64) {
    if (!base64 || base64 == "") base64 = this._defaultImage;

    var img = document.createElement("img");
    img.src = base64;
    return img;
  }
}]);

TerrainEffect.defaultOptions = {
  /**
   * 地形可见用
   * @type {boolean}
   * @default true
   * @instance
   * @memberof TerrainEffect
   */
  show: true,
  /**
   * 地形光照
   * @type {boolean}
   * @default false
   * @instance
   * @memberof TerrainEffect
   */
  enableLighting: false,
  /**
   * 高程着色
   * @type {TerrainEffect.ElevationRamp}
   * @default  null
   * @instance
   * @memberof TerrainEffect
   */
  elevation: null,
  /**
   * 坡度着色
   * @type {TerrainEffect.SlopeRamp}
   * @default  null
   * @instance
   * @memberof TerrainEffect
   */
  slope: null,
  /**
   * 坡向着色
   * @type {TerrainEffect.AspectRamp}
   * @default  null
   * @instance
   * @memberof TerrainEffect
   */
  aspect: null,
  /**
   * 等高线
   * @type {TerrainEffect.Coutour}
   * @default null
   * @instance
   * @memberof TerrainEffect
   */
  contour: null,
  /**
   * 地形限制(地形剖切)
   * @type {TerrainEffect.Restrict}
   * @default null
   * @instance
   * @memberof TerrainEffect
   */
  restrict: null,
  /**
   * 深度检测
   * @type {boolean}
   * @default false
   * @instance
   * @memberof TerrainEffect
   */
  depthTest: false,
  /**
   * 地形三角网
   * @type {boolean}
   * @default false
   * @instance
   * @memberof TerrainEffect
   */
  wireFrame: false,
  /**
   * 对数深度
   * @type {boolean}
   * @default true
   * @instance
   * @memberof TerrainEffect
   */
  logDepth: true,
  /**
   * 地形夸张
   * @type {number}
   * @default 1.0
   * @instance
   * @memberof TerrainEffect
   */
  exaggeration: 1.0,
  /**
   * 启用地下模式
   * @type {boolean}
   * @default false
   * @instance
   * @memberof TerrainEffect
   */
  subSurfaceEnabled: false,
  /**
   * 地表不透明度
   * @description 0.0表示完全透明，1.0表示完全不透明，注意地形深度检测(depthTest)关闭以后此属性才起作用！
   * @type {number}
   * @default 1.0
   * @instance
   * @memberof TerrainEffect
   */
  surfaceOpacity: 0.0,
  /**
   * 全球背景颜色
   * @instance
   * @type {number[]}
   * @memberof Effect
   */
  baseColor: [0, 0, 0.5, 1]
};

export default TerrainEffect;
